home *** CD-ROM | disk | FTP | other *** search
/ Resource for Source: C/C++ / Resource for Source - C-C++.iso / misc_src / cslib16b / csdbgen / demo.cpp < prev    next >
C/C++ Source or Header  |  1995-11-01  |  19KB  |  609 lines

  1. /////////////////////////////////////////////////////////
  2. //     Implementation file of database class: NAC.
  3. //                                                          
  4. //     Source generated by: CSDBGEN version 1.2.b.
  5. //     Date of generation:  Thursday, 2 March 1995.
  6. //     Time of generation:  12:02:10.
  7. //                                                          
  8. //                                                          
  9. //     The next lines represent the database definition     
  10. //     file used as input for CSDBGEN.                      
  11. //                                                          
  12. //                                                          
  13. ////////////// Start of the .def file //////////////////
  14. /*
  15. class: NAC
  16. record: nac_record
  17. file: dbfile
  18. field: name s 40 T
  19. field: address s 30 Y
  20. field: city s 20 Y
  21. field: birthday d Y4MD Y
  22. field: salary f
  23. */
  24. /////////////// End of .def file //////////////////////////////////////////////
  25. /*
  26.  
  27.  
  28.  
  29.                  █████     █                       █        
  30.                 ██   ██   ██                      ██        
  31.                 ███      ████     ███   ██ ███   ████       
  32.                   ███     ██        ██   ███ ██   ██        
  33.                     ███   ██     █████   ██       ██        
  34.                 ██   ██   ██ █  ██  ██   ██       ██ █      
  35.                  █████     ██    ███ ██  ██        ██       
  36.                                                             
  37.                                                             
  38.              ████     ████  ██  ██  ██ ███   █████   ████   
  39.             ██       ██  ██ ██  ██   ███ ██ ██   █  ██  ██  
  40.              ████    ██  ██ ██  ██   ██     ██      ██████  
  41.                 ██   ██  ██ ██  ██   ██     ██   █  ██      
  42.              ████     ████   ███ ██  ██      █████   █████  
  43.                                                             
  44.  
  45.  
  46. */
  47. //////////////////////////////////////////////////////////////////////////////
  48.  
  49. #include "demo.h"
  50.  
  51. extern unsigned _stklen=7000;  //A large stack is needed
  52.  
  53.  
  54. ///////////////////////////////// Constructor ////////////////////////////////
  55. NAC::NAC(void) 
  56.     is_open=FALSE; 
  57.     current=1; 
  58.     _birthday.format(Y4MD); 
  59. }
  60.  
  61. ///////////////////////////////// reindex ////////////////////////////////////
  62. void NAC::reindex(void) 
  63. {
  64.     U32 l=current;  
  65.     nac_record *rp;  
  66.     in1.empty(); 
  67.     in2.empty(); 
  68.     in3.empty(); 
  69.     in4.empty(); 
  70.     for(current=numrec(); current>0; current--)  
  71.     {                          
  72.        rp=(nac_record *)db.locate_rec(current);  
  73.        tokenize(rp->_name,&NAC::in1_ins_tok); 
  74.        in2.insert(rp->_address,¤t); 
  75.        in3.insert(rp->_city,¤t); 
  76.        in4.insert(&rp->__birthday,¤t); 
  77.     }                          
  78.     current=l;                 
  79. }
  80.  
  81. /////////////// go_to ////////////////////////////////////////////
  82. void NAC::go_to(long n) 
  83. {
  84.     if(order()!=UNSORTED) 
  85.     {
  86.       csmess_p(7110,"NAC"); 
  87.       return; 
  88.     }
  89.     write_rec(); 
  90.     current=max(min(n,db.numrec()),1); 
  91.     read_rec(); 
  92. }
  93.  
  94. /////////////// append blank//////////////////////////////////////
  95. void NAC::append_blank(void) 
  96. {
  97.        append();
  98.        tokenize(recp->_name,&NAC::in1_ins_tok); 
  99.        in2.insert(rec._address,¤t); 
  100.        in3.insert(rec._city,¤t); 
  101.        in4.insert(&rec.__birthday,¤t); 
  102. }
  103.  
  104. ///////////////////////////////// append /////////////////////////////////////
  105. // This function doesn't update the indexes, which can save some 
  106. // disk I/O because you are likely to alter the fields 
  107. // immediately after you have appended the record.
  108. // However, if you have an index on a field you don't update, this 
  109. // record will NOT appear in that particular index! 
  110. // The 'append_blank' function does update all indexes, which 
  111. // makes it a safer, but slower option. 
  112. //  
  113. void NAC::append(void) 
  114. {
  115.     write_rec();
  116.     memset(&rec,0,sizeof(nac_record)); 
  117.     current=db.append_rec(&rec); 
  118.     recp=(nac_record *)db.locate_rec(current); 
  119.     dirty=TRUE;    
  120.     _birthday.sem_jul(0L);
  121. }
  122.  
  123. ///////////////////////////////// open ///////////////////////////////////////
  124. void NAC::open(void) 
  125. {
  126.      if(is_open) return; 
  127.      int needs_reindex=FALSE;        
  128.      dirty=FALSE;        
  129.  
  130. #ifdef _Windows
  131.      int fre=300/9; //Use 300 Kb for buffers. You may increase this.
  132. #else
  133.      int fre=(int)(coreleft()-100000L)/9/1024;
  134.      fre=max(fre,0); 
  135. #endif
  136.  
  137.      if(!db.open("dbfile.dbf",fre)) 
  138.      {
  139.          csmess_disp("FATAL: Can't open database dbfile.dbf.");
  140.          exit(1);
  141.      }
  142.      if(db.lengthrec()!=sizeof(nac_record)) 
  143.      {
  144.          csmess_disp("FATAL: wrong record size.\n\rProbably wrong or old database file.");
  145.          db.close(); 
  146.          exit(1); 
  147.      }
  148.      if(!file_exist("dbfile01.idx"))
  149.      { 
  150.        in1.multiple_keys(TRUE);
  151.        in1.define("dbfile01.idx",NAME_LENGTH/2,sizeof(long));
  152.        needs_reindex=TRUE; 
  153.      } 
  154.      in1.open("dbfile01.idx",fre*2);
  155.   
  156.      if(!file_exist("dbfile02.idx"))
  157.      { 
  158.        in2.multiple_keys(TRUE);
  159.        in2.define("dbfile02.idx",ADDRESS_LENGTH+1,sizeof(long));
  160.        needs_reindex=TRUE; 
  161.      } 
  162.      in2.open("dbfile02.idx",fre*2);
  163.   
  164.      if(!file_exist("dbfile03.idx"))
  165.      { 
  166.        in3.multiple_keys(TRUE);
  167.        in3.define("dbfile03.idx",CITY_LENGTH+1,sizeof(long));
  168.        needs_reindex=TRUE; 
  169.      } 
  170.      in3.open("dbfile03.idx",fre*2);
  171.   
  172.      if(!file_exist("dbfile04.idx"))
  173.      { 
  174.        in4.multiple_keys(TRUE);
  175.        in4.define("dbfile04.idx",sizeof(long),sizeof(long));
  176.        needs_reindex=TRUE; 
  177.      } 
  178.      in4.open("dbfile04.idx",fre*2);
  179.   
  180.      if(needs_reindex) reindex(); 
  181.      is_open=TRUE; 
  182.      if(numrec()==0) append_blank();
  183.      else            read_rec(); 
  184.   
  185.      order(UNSORTED);  
  186. }
  187.  
  188. ///////////////////////////////// close //////////////////////////////////////
  189. void NAC::close(void) 
  190. {
  191.      if(!is_open) return; 
  192.      write_rec(); 
  193.      db.close(); 
  194.      in1.close();
  195.      in2.close();
  196.      in3.close();
  197.      in4.close();
  198.      is_open=FALSE; 
  199. }
  200.  
  201. ///////////////////////////////// define /////////////////////////////////////
  202. void NAC::define(void) 
  203. {
  204.      db.define("dbfile.dbf",sizeof(nac_record)); 
  205.      in1.multiple_keys(TRUE);
  206.      in1.define("dbfile01.idx",NAME_LENGTH/2,sizeof(long));
  207.      in2.multiple_keys(TRUE);
  208.      in2.define("dbfile02.idx",ADDRESS_LENGTH+1,sizeof(long));
  209.      in3.multiple_keys(TRUE);
  210.      in3.define("dbfile03.idx",CITY_LENGTH+1,sizeof(long));
  211.      in4.multiple_keys(TRUE);
  212.      in4.define("dbfile04.idx",sizeof(long),sizeof(long));
  213. }
  214.  
  215. ///////////////////////////////// pack ///////////////////////////////////////
  216. void NAC::pack(void) 
  217. {
  218.      write_rec(); 
  219.      db.pack();
  220.      reindex();
  221.      if(numrec()==0) append_blank();
  222.      top();
  223. }
  224.  
  225. ///////////////////////////////// skip ///////////////////////////////////////
  226. int  NAC::skip0(int delta) 
  227. {
  228.      long old_current=current; 
  229.      current=max(min(current+delta,db.numrec()),1); 
  230.      return current-old_current; 
  231. }
  232.  
  233. int  NAC::skip(int delta) 
  234. {
  235.      int rc; 
  236.      write_rec(); 
  237.      rc=(this->*skip_fun)(delta); 
  238.      read_rec(); 
  239.      return rc; 
  240. }
  241.  
  242. ///////////////////////////////// order //////////////////////////////////////
  243. void NAC::order(int nr) 
  244. {
  245.      switch(nr)
  246.      {
  247.          case 0:        //Unsorted 
  248.                   bof_fun   =&NAC::bof0;
  249.                   eof_fun   =&NAC::eof0;
  250.                   skip_fun  =&NAC::skip0;
  251.                   top_fun   =&NAC::top0;
  252.                   bottom_fun=&NAC::bottom0;
  253.                   search_fun=&NAC::search0;
  254.                   break; 
  255.          case 1:        //Index on field name
  256.                   bof_fun   =&NAC::bof1;
  257.                   eof_fun   =&NAC::eof1;
  258.                   skip_fun  =&NAC::skip1;
  259.                   top_fun   =&NAC::top1;
  260.                   bottom_fun=&NAC::bottom1;
  261.                   search_fun=&NAC::search1;
  262.                   break; 
  263.          case 2:        //Index on field address
  264.                   bof_fun   =&NAC::bof2;
  265.                   eof_fun   =&NAC::eof2;
  266.                   skip_fun  =&NAC::skip2;
  267.                   top_fun   =&NAC::top2;
  268.                   bottom_fun=&NAC::bottom2;
  269.                   search_fun=&NAC::search2;
  270.                   break; 
  271.          case 3:        //Index on field city
  272.                   bof_fun   =&NAC::bof3;
  273.                   eof_fun   =&NAC::eof3;
  274.                   skip_fun  =&NAC::skip3;
  275.                   top_fun   =&NAC::top3;
  276.                   bottom_fun=&NAC::bottom3;
  277.                   search_fun=&NAC::search3;
  278.                   break; 
  279.          case 4:        //Index on field birthday
  280.                   bof_fun   =&NAC::bof4;
  281.                   eof_fun   =&NAC::eof4;
  282.                   skip_fun  =&NAC::skip4;
  283.                   top_fun   =&NAC::top4;
  284.                   bottom_fun=&NAC::bottom4;
  285.                   search_fun=&NAC::search4;
  286.                   break; 
  287.          default: return; // Function called with wrong parameter.
  288.      }
  289.      iOrder=nr;
  290.      top();
  291. }
  292. /////////////////////////////writing record  ///////////////////////////////
  293. void NAC::write_rec2(void) 
  294. {
  295.     if(strcmp(recp->_name,rec._name)) 
  296.     { 
  297.       tokenize(recp->_name,&NAC::in1_del_tok); 
  298.       tokenize(rec._name,&NAC::in1_ins_tok); 
  299.     } 
  300.     if(strcmp(recp->_address,rec._address)) 
  301.     { 
  302.       in2.delet(recp->_address,¤t); 
  303.       in2.insert(rec._address,¤t); 
  304.     } 
  305.     if(strcmp(recp->_city,rec._city)) 
  306.     { 
  307.       in3.delet(recp->_city,¤t); 
  308.       in3.insert(rec._city,¤t); 
  309.     } 
  310.     rec.__birthday=_birthday.sem_jul(); 
  311.     if(recp->__birthday!=rec.__birthday) 
  312.     { 
  313.       in4.delet(&recp->__birthday,¤t); 
  314.       in4.insert(&rec.__birthday,¤t); 
  315.     } 
  316.     db.write_rec(current,&rec); 
  317.     dirty=FALSE;   
  318. }
  319.  
  320. ///////////////////////////////// export /////////////////////////////////////
  321. int  NAC::export(char *s) 
  322. {
  323.      FILE *fo=fopen(s,"w"); 
  324.      if(fo==NULL) return FALSE; 
  325.  
  326.      write_rec();
  327.      fprintf(fo,"class:  NAC");
  328.      fprintf(fo,"\nrecord: nac_record");
  329.      fprintf(fo,"\nfile:   dbfile");
  330.      fprintf(fo,"\nfield:  name s 40 Y");
  331.      fprintf(fo,"\nfield:  address s 30 Y");
  332.      fprintf(fo,"\nfield:  city s 20 Y");
  333.      fprintf(fo,"\nfield:  birthday d Y");
  334.      fprintf(fo,"\nfield:  salary f  ");
  335.  
  336.      if(ferror(fo)) { fclose(fo); return FALSE; } 
  337.  
  338.      nac_record *recp;
  339.      DATE conv;
  340.      conv.format(Y4MD);
  341.      for(long l=numrec();l>0;l--) 
  342.      {
  343.         recp=( nac_record * )db.locate_rec(l);
  344.         fprintf(fo,"\n%c",12);
  345.         fprintf(fo,"\n%s",recp->_name);
  346.         fprintf(fo,"\n%s",recp->_address);
  347.         fprintf(fo,"\n%s",recp->_city);
  348.         conv.sem_jul(recp->__birthday);
  349.         fprintf(fo,"\n%s",(char *)conv);
  350.         fprintf(fo,"\n%g",recp->_salary);
  351.         fprintf(fo,"\n"); //Additional linefeed, to avoid trouble!
  352.  
  353.         if(ferror(fo)) { fclose(fo); return FALSE; } 
  354.      }
  355.      return !fclose(fo);  
  356. }
  357.  
  358. ///////////////////////////////// import /////////////////////////////////////
  359. int NAC::import(char *s) 
  360. {   
  361.  
  362.       FILE *fr=fopen(s,"r"); 
  363.       if(fr==NULL) return FALSE;
  364.   
  365.   
  366. #define MAX_NUM_FIELDS  100   //Increase this to allow more fields    
  367. #define MAX_FIELD_LEN   500   //Increase this to allow longer fields  
  368.  
  369.       int *finu;
  370.       finu=(int *)malloc(MAX_NUM_FIELDS*sizeof(int));
  371.       if(finu==NULL) { fclose(fr); return FALSE; }   
  372.  
  373.       char *fibu;    
  374.       fibu=(char *)malloc(MAX_FIELD_LEN);
  375.       if(fibu==NULL) { fclose(fr); free(finu); return FALSE; } 
  376.       *fibu=0;  
  377.  
  378.       char *fipo=fibu+strlen("field:");  
  379.       char *cp; 
  380.       int  ifieldnr=0;    
  381.       int  ofieldnr; 
  382.       DATE conv;
  383.       conv.format(Y4MD);
  384.  
  385.       memset(finu,0,MAX_NUM_FIELDS*sizeof(int));
  386.  
  387.       fgets(fibu,MAX_FIELD_LEN,fr); 
  388.       while(!strchr(fibu,12))  
  389.       {    
  390.         strlwr(fibu);
  391.         notabs(fibu);
  392.         trim_string(fibu);
  393.         if(strstr(fibu,"field:"))   
  394.         {  
  395.            ifieldnr++;  
  396.            trim_string(fipo);    
  397.            if((cp=strchr(fipo,' '))!=NULL) *cp=0;
  398.            if     (!strcmp(fipo,"name"))    ofieldnr=1;
  399.            else if(!strcmp(fipo,"address"))    ofieldnr=2;
  400.            else if(!strcmp(fipo,"city"))    ofieldnr=3;
  401.            else if(!strcmp(fipo,"birthday"))    ofieldnr=4;
  402.            else if(!strcmp(fipo,"salary"))    ofieldnr=5;
  403.            else ofieldnr=0; 
  404.            finu[ifieldnr]=ofieldnr; 
  405.         }  
  406.         fgets(fibu,MAX_FIELD_LEN,fr);    
  407.       }    
  408.  
  409.  
  410.  
  411.       for(;;)   
  412.       {    
  413.         if(!strchr(fibu,12))   
  414.         {  
  415.            ifieldnr++; 
  416.            if(ifieldnr<MAX_NUM_FIELDS) 
  417.              switch(finu[ifieldnr])   
  418.              {  
  419.                 case 0:  break;
  420.                 case 1:
  421.                          fibu[NAME_LENGTH]=0;
  422.                          name(fibu);
  423.                          break;
  424.                 case 2:
  425.                          fibu[ADDRESS_LENGTH]=0;
  426.                          address(fibu);
  427.                          break;
  428.                 case 3:
  429.                          fibu[CITY_LENGTH]=0;
  430.                          city(fibu);
  431.                          break;
  432.                 case 4:
  433.                          conv=fibu;
  434.                          _birthday.sem_jul(conv.sem_jul());
  435.                          break;
  436.                 case 5:
  437.                          salary(atof(fibu));
  438.                          break;
  439.              }  
  440.         }  
  441.         else    
  442.         {  
  443.            ifieldnr=0; 
  444.            append_blank();
  445.         }  
  446.         if(feof(fr)) break;    
  447.         fgets(fibu,MAX_FIELD_LEN,fr);    
  448.         cp=fibu+(max(1,strlen(fibu))-1); 
  449.         if(*cp=='\n') *cp=0;  //removing the line feed 
  450.       }    
  451.  
  452.  
  453.       fclose(fr); 
  454.       free(fibu); 
  455.       free(finu); 
  456.  
  457. #undef MAX_NUM_FIELDS
  458. #undef MAX_FIELD_LEN 
  459.  
  460.  return TRUE; 
  461. }
  462.  
  463. ///////////////////////////////// export to dBASE compatible file. ///////////
  464. int NAC::to_DBASE(char *s) 
  465. {   
  466.  
  467.       char bufje[12];
  468.       if(!is_open) return FALSE;
  469.  
  470.       write_rec(); 
  471.       FILE *fo=fopen(s,"wb"); 
  472.       if(fo==NULL) return FALSE;
  473.   
  474.       int i;
  475.   
  476.       DATE d_upda;
  477.       d_upda.sem_jul(db.sj_updated());
  478.       fputc(03,fo);  
  479.       
  480.       fputc(d_upda.year()%100,fo);  
  481.       fputc(d_upda.month(),fo);  
  482.       fputc(d_upda.day(),fo);  
  483.  
  484.       long nr_record=numrec(); 
  485.       fwrite(&nr_record,sizeof(long),1,fo); 
  486.       putw(194,fo);        //Header length 
  487.       putw(113,fo);        //Length of data record 
  488.       for(i=0;i<20;i++) fputc(0,fo); // 20 dummy bytes 
  489.  
  490.  
  491. // Writing definition of field name to dbase file header.
  492.       memset(bufje,0,11);
  493.       strcpy(bufje,"NAME");
  494.       fwrite(bufje,11,1,fo);
  495.       fputc('C',fo); 
  496.       for(i=0;i<4;i++) fputc(0,fo); // 4 dummy bytes 
  497.       fputc(40,fo); 
  498.       fputc(0,fo); 
  499.       for(i=0;i<14;i++) fputc(0,fo); // 14 dummy bytes 
  500.  
  501. // Writing definition of field address to dbase file header.
  502.       memset(bufje,0,11);
  503.       strcpy(bufje,"ADDRESS");
  504.       fwrite(bufje,11,1,fo);
  505.       fputc('C',fo); 
  506.       for(i=0;i<4;i++) fputc(0,fo); // 4 dummy bytes 
  507.       fputc(30,fo); 
  508.       fputc(0,fo); 
  509.       for(i=0;i<14;i++) fputc(0,fo); // 14 dummy bytes 
  510.  
  511. // Writing definition of field city to dbase file header.
  512.       memset(bufje,0,11);
  513.       strcpy(bufje,"CITY");
  514.       fwrite(bufje,11,1,fo);
  515.       fputc('C',fo); 
  516.       for(i=0;i<4;i++) fputc(0,fo); // 4 dummy bytes 
  517.       fputc(20,fo); 
  518.       fputc(0,fo); 
  519.       for(i=0;i<14;i++) fputc(0,fo); // 14 dummy bytes 
  520.  
  521. // Writing definition of field birthday to dbase file header.
  522.       memset(bufje,0,11);
  523.       strcpy(bufje,"BIRTHDAY");
  524.       fwrite(bufje,11,1,fo);
  525.       fputc('D',fo); 
  526.       for(i=0;i<4;i++) fputc(0,fo); // 4 dummy bytes 
  527.       fputc(8,fo); 
  528.       fputc(0,fo); 
  529.       for(i=0;i<14;i++) fputc(0,fo); // 14 dummy bytes 
  530.  
  531. // Writing definition of field salary to dbase file header.
  532.       memset(bufje,0,11);
  533.       strcpy(bufje,"SALARY");
  534.       fwrite(bufje,11,1,fo);
  535.       fputc('N',fo); 
  536.       for(i=0;i<4;i++) fputc(0,fo); // 4 dummy bytes 
  537.       fputc(14,fo); 
  538.       fputc(7,fo); 
  539.       for(i=0;i<14;i++) fputc(0,fo); // 14 dummy bytes 
  540.  
  541.  
  542.       fputc(13,fo);  //Field terminator 
  543.       fputc(0,fo); 
  544.  
  545. // By now we have written the definition of the 
  546. // record structure to the file header. 
  547. // From here on we will export the records. 
  548.  
  549.      nac_record *recp;
  550.      for(long l=numrec();l>0;l--) 
  551.      {
  552.  
  553.         if(ferror(fo)) { fclose(fo); return FALSE; } 
  554.         recp=(nac_record *)db.locate_rec(l);
  555.  
  556.         if(db.is_delet(l)) fputc(42,fo); 
  557.         else               fputc(32,fo); 
  558.  
  559. /////////////////////// writing field name /////////////
  560.         fprintf(fo,"%-40s",recp->_name);
  561. /////////////////////// writing field address /////////////
  562.         fprintf(fo,"%-30s",recp->_address);
  563. /////////////////////// writing field city /////////////
  564.         fprintf(fo,"%-20s",recp->_city);
  565. /////////////////////// writing field birthday /////////////
  566.         if(recp->__birthday)
  567.         { 
  568.           d_upda.sem_jul(recp->__birthday);
  569.           fprintf(fo,"%4d",d_upda.year4());
  570.           fprintf(fo,"%02d",d_upda.month());
  571.           fprintf(fo,"%02d",d_upda.day());
  572.         } 
  573.         else 
  574.         { 
  575.           fprintf(fo,"        "); 
  576.         } 
  577. /////////////////////// writing field salary /////////////
  578.         fprintf(fo,"%14.7f",recp->_salary);
  579.      }
  580.      fputc(26,fo);  //End of File 
  581.      fclose(fo); 
  582.  
  583.  return TRUE; 
  584. }
  585.  
  586. ///////////////////////////////// tokenize field ///////////////////////
  587. void NAC::tokenize(char *s,void(NAC::*fun)(void *))
  588. {
  589.  
  590.      char delim[]="\t,()- "; //Token delimiters
  591.      const min_len=4;  //Minimum length for a token to be indexed.
  592.      char *p,*q=s;
  593.      char c;
  594.      int  insert=FALSE;
  595.  
  596.      p=strpbrk(q,delim);
  597.      while(p)
  598.      {
  599.         c=*p; *p=0;
  600.         if(strlen(q)>=min_len) { (this->*fun)(q); insert=TRUE; }
  601.         *p=c;
  602.         do{ p=strpbrk(q=p+1,delim); }while(q==p);
  603.      }
  604.  
  605.      if(strlen(q)>=min_len) { (this->*fun)(q); insert=TRUE; }
  606.      if(!insert) (this->*fun)(s);
  607.  
  608. }